# -*- coding: utf-8 -*-
# Copyright 2009 Marc Ponce Plaza - marcpp@gmail.com
# 
# This program is free software; you can redistribute it and/or modify it under the 
# terms of the GNU General Public License as published by the Free Software Foundation; 
# either version 2 of the License, or (at your option) any later version. This program 
# is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
# See the GNU General Public License for more details. You should have received a copy 
# of the GNU General Public License along with this program; if not, write to the Free 
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.


import gtk
import gtk.glade
import time
from datetime import datetime
from xml.dom import minidom

""" Variables d'usuari per a la configuració del programa """
defectetoteldia = 0	# Marca tot el dia
defectehoresazero = 0	# Posa l'hora i minuts a zero sempre.
idioma = 'esp'	# Disponibles "cat" català y "esp" castellano

class EnGoCa:
	""" Programa EnGoCa """	

	def __init__(self, runaslib=True):
		
		################################################################
		#  Interface gràfica
		################################################################
		
		# Load Glade XML
		if (idioma == 'cat'):
			self.xml = gtk.glade.XML("EnGoCa.cat.glade")
		if (idioma == 'esp'):
			self.xml = gtk.glade.XML("EnGoCa.esp.glade")
		
		# Get Window
		self.w = self.xml.get_widget('window1')
		self.w.connect("delete_event", gtk.main_quit)
		
		self.sobre = self.xml.get_widget('sobre')
		self.confirmacio = self.xml.get_widget('confirmacio')
		self.configuracio = self.xml.get_widget('configuracio')
		
		# Get Windows child
		self.w_child = self.w.get_child()
		
		# Obtenir controls menu
		self.menu_sortir = self.xml.get_widget('menu_sortir')
		self.menu_sobre = self.xml.get_widget('menu_sobre')
		self.menu_configuracio = self.xml.get_widget('menu_configuracio')
		
		# Obtenir controls finestra ppal
		self.btn_calendari = self.xml.get_widget('btncalendari')
		self.calendaris = self.xml.get_widget('calendaris')
		self.event = self.xml.get_widget('event')
		self.duratoteldia = self.xml.get_widget('duratoteldia')
		self.datai = self.xml.get_widget('datai')
		self.horai = self.xml.get_widget('horai')
		self.minutsi = self.xml.get_widget('minutsi')		
		self.dataf = self.xml.get_widget('dataf')
		self.horaf = self.xml.get_widget('horaf')
		self.minutsf = self.xml.get_widget('minutsf')
		self.btn_aceptar = self.xml.get_widget('aceptar')
		self.barraestat = self.xml.get_widget('barraestat')
		
		# Obtenir controls finestra confirmació
		self.conf_calendari = self.xml.get_widget('confirmacio-calendari')
		self.conf_event = self.xml.get_widget('confirmacio-event')
		self.conf_inici = self.xml.get_widget('confirmacio-inici')
		self.conf_fi = self.xml.get_widget('confirmacio-fi')
		self.btn_conf_aceptar = self.xml.get_widget('confirmacio-aceptar')
		self.btn_conf_cancelar = self.xml.get_widget('confirmacio-cancelar')

		# Obtenir controls finestra configuració
		self.config_config = self.xml.get_widget('configuracio-config')
		
		# Connectar funcions als botons
		# Menu
		self.menu_sortir.connect("activate", gtk.main_quit)
		self.menu_sobre.connect("activate", self.on_btn_sobre)
		self.menu_configuracio.connect("activate", self.on_btn_configuracio)
		
		# Finestra principal
		self.btn_aceptar.connect('clicked', self.on_btn_aceptar)
		self.btn_calendari.connect('clicked', self.on_btn_calendaris)
		self.duratoteldia.connect('clicked', self.on_duratoteldia)
		# Finestra confirmació
		self.btn_conf_aceptar.connect('clicked', self.on_btn_afegir_event)
		self.btn_conf_cancelar.connect('clicked', self.on_btn_cancelar)

		# self.widget will be attached to the Activity
		# This can be any GTK widget except a window
		self.widget = self.w_child

		
		################################################################
		#  A l'inici del programa
		################################################################		
		
		# Si no hi ha cap calendari configurat, es mostra la finestra de configuració
		if not configuracioBBDD().taula_calendaris:
			configuracio()
		
		# Llistat de calendaris
		self.assignar_dades_llista()

		# Posa tots els camps al valor predeterminat
		self.reset()		
	
		################################################################
		# Inicia l'interface gràfica
		################################################################	
		if not runaslib:
			self.w.show_all()
			gtk.main()		


	def reset (self):
	# Posa els camps al seu valor per defecte	
	
		if (defectetoteldia == 1):
			self.duratoteldia.set_active(True)

		self.datai = self.xml.get_widget('datai')
		mes = self.preparar_data("M")
		mes = mes - 1
		anny = self.preparar_data("A")
		dia = self.preparar_data("D")
		# Data inicial
		self.datai.select_month(mes,anny)
		self.datai.select_day(dia)
		self.datai.mark_day(self.preparar_data("D"))
		# Data final
		self.dataf.select_month(mes,anny)
		self.dataf.select_day(dia)
		self.dataf.mark_day(self.preparar_data("D"))
		
		if (defectehoresazero == 1):
			self.horai.set_value(00)
			self.minutsi.set_value(00)
			self.horaf.set_value(00)
			self.minutsf.set_value(00)
		else:
			# Hora inicial
			self.horai.set_value(self.preparar_hora("I"))
			self.minutsi.set_value(00)
			# Hora final
			self.horaf.set_value(self.preparar_hora("F"))
			self.minutsf.set_value(00)
			
		# Camp d'entrada de text de l'event
		self.event.set_text("")


	def finestra_confirmacio (self):
	# Mostra la finestra de confirmació de l'event amb les dades introduïdes i 
	# depura els errors.
		self.conf_calendari.set_text(self.calendaris.get_active_text())
		self.conf_event.set_text(self.event.get_text())
		# Data i hora d'inici
		anyi, mesi, diai = self.datai.get_date()
		mesi = mesi + 1
		inici = datetime(anyi, mesi, diai, int(self.horai.get_text()), int(self.minutsi.get_text()))
		self.conf_inici.set_text(str(inici))
		
		# Data i hora fi
		anyf, mesf, diaf = self.dataf.get_date()
		mesf = mesf + 1
		fi = datetime(anyf, mesf, diaf, int(self.horaf.get_text()), int(self.minutsf.get_text()))
		self.conf_fi.set_text(str(fi))
		
		# Mostra la finestra		
		self.calendaris.get_active_text()
		self.confirmacio.show()


	def preparar_data (self,dma):
	# Prepara la data d'inici (data actual).
	# Retorna D M A o tot junt depenent del paràmetre d'entrada.
		sdia = time.strftime("%d", time.localtime())
		dia = int(sdia)
		smes = time.strftime("%m", time.localtime())
		mes = int(smes)
		sanny = time.strftime("%Y", time.localtime())
		anny = int(sanny)		
		data = time.strftime('%Y-%m-%d', time.localtime())

		if dma == "D":
			return dia
		if dma == "M":
			return mes
		if dma == "A":
			return anny
		if dma == "data":
			return data


	def preparar_hora (self,inicialofinal):
	# Prepara l'hora inicial a l'hora actual (només hora, minuts no) i l'hora
	# final amb 1 hora mes.
		shora_inicial = time.strftime("%H", time.localtime())
		hora_inicial = int(shora_inicial)
		hora_final = hora_inicial + 1
		if inicialofinal == "I":
			return hora_inicial
		if inicialofinal == "F":
			return hora_final


	def assignar_dades_llista (self, *args):
	# Carrega la llista de calendaris amb els calendaris de la configuració
		contador = 0
		for item in configuracioBBDD().taula_calendaris:
			if (item["visible"] == "si"):   # Si el calendari és visible, l'afegeix a la llista
				self.calendaris.insert_text (item["id"],item["nom"])
				contador = contador + 1
		if contador == 1:
			self.calendaris.set_active(0)


	def assignar_dades_connexio (self, parametre):
	# Retorna el paràmetre entrat amb el valor corresponent en base al calendari seleccionat.
		calendari_seleccionat = self.calendaris.get_active_text()
		for item in configuracioBBDD().taula_calendaris:
			if item["nom"] == calendari_seleccionat:   # Si el calendari és igual al seleccionat a la llista
				nom = item ["nom"]
				usuari = item ["usuari"]
				password = item["password"]
				direccio = item["dir"]

		if parametre == "usuari":
			return usuari
		if parametre == "password":
			return password
		if parametre == "direccio":
			return direccio


	def on_btn_calendaris (self, *args):
	# Obre enllaç al navegador
		import os
		os.startfile("http://calendar.google.com")


	def on_btn_aceptar(self, *args):
	# Comprova si hi ha errors en l'entrada de dades i crida a preparar 
	# finestra confirmació
		error = 0
		self.barraestat.pop(1)	# Esborra el que hi ha a la barra d'estat
		## Comprovació de que el selector de calendaris té seleccionat algún valor.
		valor = self.calendaris.get_active()
		if valor < 0:
			self.barraestat.push(1,"Error, has de seleccionar algún calendari!")
			error = 1	
		## Comprovació de que el camp Event no está buit.
		if error != 1:
			if self.event.get_text() == '':
				self.barraestat.push(1,"Error, has d'introduïr el text de l'event!")
				error = 1
		## Comprovació de les dates
		if error != 1:
			anyi, mesi, diai = self.datai.get_date()
			mesi = mesi + 1
			anyf, mesf, diaf = self.dataf.get_date()
			mesf = mesf + 1
#			# Si la data de fi > data inici, error!
			horai = datetime(anyi, mesi, diai, int(self.horai.get_text()), int(self.minutsi.get_text()))
			horaf = datetime(anyf, mesf, diaf, int(self.horaf.get_text()), int(self.minutsf.get_text()))
			if horaf < horai:
				self.barraestat.push(1,"Error, l'inici de l'event ha de ser posterior al fi!")
				error = 1				

		# Si no hi ha cap error, mostra la finestra de confirmació
		if error == 0:
			self.finestra_confirmacio()


	def on_duratoteldia (self, *args):
	# Si l'event dura tot el dia, totes les hores i minuts a zero.
		self.horai.set_value(0)
		self.minutsi.set_value(0)
		self.horaf.set_value(0)
		self.minutsf.set_value(0)


	def on_btn_afegir_event (self, *args):
		
		try:
			from xml.etree import ElementTree # for Python 2.5 users
		except ImportError:
			from elementtree import ElementTree
		import gdata.calendar.service
		import gdata.service
		import atom.service
		import gdata.calendar
		import atom
		import getopt
		import sys
		import string
		
		calendari_event = self.calendaris.get_active_text()
		text_event = ('%s' % self.event.get_text())
		toteldia = int(self.duratoteldia.get_active())

		
		# Prepara data i hora en base a si l'event dura tot el dia o no.
		# Si dura tot el dia, només s'ha d'enviar la data, l'hora no!
		anyi, mesi, diai = self.datai.get_date()
		mesi = mesi + 1		
		anyf, mesf, diaf = self.dataf.get_date()
		mesf = mesf + 1
		if toteldia == 1:
			fi_event = ('%s-%s-%s'%(anyf, mesf, diaf))
			inici_event = ('%s-%s-%s'%(anyi, mesi, diai))
		else:
			fi_event = datetime(anyf, mesf, diaf, int(self.horaf.get_text()), int(self.minutsf.get_text()))
			fi_event = str(fi_event).replace (" ", "T")
			inici_event = datetime(anyi, mesi, diai, int(self.horai.get_text()), int(self.minutsi.get_text()))
			inici_event = str(inici_event).replace (" ", "T")			

		# Enviar a Google
		calendar_service = gdata.calendar.service.CalendarService()
		calendar_service.email = self.assignar_dades_connexio("usuari")
		calendar_service.password = self.assignar_dades_connexio("password")
		calendari = "/calendar/feeds/" + self.assignar_dades_connexio("direccio") +  "/private/full"

		calendar_service.ProgrammaticLogin()
		event = gdata.calendar.CalendarEventEntry()
		event.title = atom.Title(text=text_event)
		event.content = atom.Content(text='')
		event.where.append(gdata.calendar.Where(value_string=''))
		event.when.append(gdata.calendar.When(start_time=inici_event, end_time=fi_event))		
		
		new_event = calendar_service.InsertEvent(event, calendari)
		
		# Tanca la finestra de confirmació
		self.on_btn_cancelar()	
		# Posa tots els camps al valor predeterminat
		self.reset()		
		self.barraestat.push(1,"L'event s'ha afegit correctament.")


	def on_btn_sobre(self, *args):
	# Ordre mostrar sobre
		self.sobre.show()


	def on_btn_configuracio(self, *args):
	# Ordre mostrar sobre
		configuracio()


	def on_btn_cancelar(self, *args):
	# Ordre tancar programa
		self.confirmacio.hide()



class configuracio:
	""" Configuració dels calendaris """

	def __init__(self):
		
		# Fitxer Glade
		if (idioma == 'cat'):
			self.gladefile = "config.cat.glade"
		if (idioma == 'esp'):
			self.gladefile = "config.esp.glade"
			
		self.wTree = gtk.glade.XML(self.gladefile, "configuracio") 
		self.configuracioDialog = self.wTree.get_widget("configuracio-dialog")

		# Crea el diccionari i connecta
		dic = {"on_mainWindow_destroy" : gtk.main_quit
				, "on_configuracio-afegir_clicked" : self.OnConfiguracioAfegir
				, "on_configuracio-modificar_clicked" : self.OnConfiguracioModificar
				, "on_configuracio-eliminar_clicked" : self.OnConfiguracioEliminar
				, "on_tancar_programa_clicked" : gtk.main_quit}
		self.wTree.signal_autoconnect(dic)

		# Variables per a les columnes del visor de configuració
		self.cID = 0
		self.cVisible = 1
		self.cNom = 2
		self.cUsuari = 3
		self.cPassword = 4
		self.cDireccio = 5

		self.sID = ""
		self.sVisible = "Visible"
		self.sNom = "Nom calendari"
		self.sUsuari = "Usuari Google"
		self.sPassword = "Password Google"
		self.sDireccio = "ID calendari"
				
		# Obté el treeView
		self.visorConfiguracio = self.wTree.get_widget("configuracio-vista")
		
		# Afegeix les columnes al treeView
		self.AfegirColumnaLlista(self.sID, self.cID)
		self.AfegirColumnaLlista(self.sVisible, self.cVisible)
		self.AfegirColumnaLlista(self.sNom, self.cNom)
		self.AfegirColumnaLlista(self.sUsuari, self.cUsuari)
		self.AfegirColumnaLlista(self.sPassword, self.cPassword)
		self.AfegirColumnaLlista(self.sDireccio, self.cDireccio)
		
		# Crea el ListStore per a la llista de calendaris
		self.configuracioLlista = gtk.ListStore(str, str, str, str, str, str)
		# Enllaça el ListStore al TreeView
		self.visorConfiguracio.set_model(self.configuracioLlista)	
		
		# Carrega la llista amb la lectura de la BBDD
		self.rellenarLlista()
		
		
	def AfegirColumnaLlista(self, title, columnId):
		column = gtk.TreeViewColumn(title, gtk.CellRendererText()
			, text=columnId)
		column.set_resizable(True)		
		column.set_sort_column_id(columnId)
		self.visorConfiguracio.append_column(column)
		
		
	def OnConfiguracioAfegir(self, widget):
		#Crear la finestra de dialog
		dialog = gtk.glade.XML(self.gladefile, "configuracio-dialog") 
		configuracioDialog = dialog.get_widget("configuracio-dialog")
		
		# Obté el control dels camps d'entrada
		nom_calendari = dialog.get_widget('configuracio-dialog_nom')
		usuari_calendari = dialog.get_widget('configuracio-dialog_usuari')
		password_calendari = dialog.get_widget('configuracio-dialog_pwd')
		direccio_calendari = dialog.get_widget('configuracio-dialog_direccio')
		visible_calendari = dialog.get_widget('configuracio-dialog_visible')		
		
		# Executa el dialog i espera resposta
		result = configuracioDialog.run()
		
		# Obté els valors dels camps d'entrada
		nom = nom_calendari.get_text()
		usuari = usuari_calendari.get_text()
		password = password_calendari.get_text()
		direccio = direccio_calendari.get_text()
		visible = visible_calendari.get_text()		
		
		if (result==gtk.RESPONSE_OK):
			# Quan es polsa Acceptar, guarda els camps a la taula
			configuracioBBDD().insertar(visible, nom, usuari, password, direccio)
		# Refresca la llista
		self.rellenarLlista()
		# Destrueix el dialog
		configuracioDialog.destroy()


	def OnConfiguracioModificar (self, widget):
		
		# Obté el valor ID del calendari seleccionat
		seleccio = self.visorConfiguracio.get_selection()
		resultat = seleccio.get_selected()
		if resultat: # resultat no pot ser blanc
			model, iter = resultat
			id_selec = self.configuracioLlista.get_value(iter,0) # Valor de la primera columna del calendari seleccionat
			
			#Crear la finestra de dialog
			dialog = gtk.glade.XML(self.gladefile, "configuracio-dialog")
			configuracioDialog = dialog.get_widget("configuracio-dialog")
			
			# Obté el control dels camps de e/s
			nom_calendari = dialog.get_widget('configuracio-dialog_nom')
			usuari_calendari = dialog.get_widget('configuracio-dialog_usuari')
			password_calendari = dialog.get_widget('configuracio-dialog_pwd')
			direccio_calendari = dialog.get_widget('configuracio-dialog_direccio')
			visible_calendari = dialog.get_widget('configuracio-dialog_visible')
			
			# Rellena els camps amb els de la BBDD
			nom_calendari.set_text(configuracioBBDD().consulta(id_selec, "nom"))
			usuari_calendari.set_text(configuracioBBDD().consulta(id_selec, "usuari"))
			password_calendari.set_text("*****")
			direccio_calendari.set_text(configuracioBBDD().consulta(id_selec, "direccio"))
			visible_calendari.set_text(configuracioBBDD().consulta(id_selec, "visible"))
			
			# Executa el dialog i espera resposta
			result = configuracioDialog.run()
			if (result==gtk.RESPONSE_OK):
				# Obté els camps modificats
				id = id_selec
				visible = visible_calendari.get_text()
				nom = nom_calendari.get_text()
				usuari = usuari_calendari.get_text()
				if (password_calendari.get_text() == "*****"):
					password = configuracioBBDD().consulta(id_selec, "password")
				else:
					password = password_calendari.get_text()
				direccio = direccio_calendari.get_text()
				# Quan es polsa Acceptar, guarda els camps a la taula
				configuracioBBDD().actualitzar(id, visible, nom, usuari, password, direccio)
			# Refresca la llista
			self.rellenarLlista()
			# Destrueix el dialog
			configuracioDialog.destroy()
		
		
	def OnConfiguracioEliminar (self, widget):
	# Elimina un element de la taula i de la llista
		seleccio = self.visorConfiguracio.get_selection()
		resultat = seleccio.get_selected()
		if resultat: #resultat no pot ser blanc
			model, iter = resultat
		#model.remove(iter) # Elimina la linea seleccionada
		id_selec = self.configuracioLlista.get_value(iter,0) # Valor de la primera columna del calendari seleccionat
		configuracioBBDD().eliminar(id_selec)
		# Refresca la llista
		self.rellenarLlista()		


	def rellenarLlista(self):
	# Rellena la llista de calendaris amb els seus valors de configuració
		# Obté en una llista els camps de la BBDD
		BBDD = configuracioBBDD()
		self.DATA = BBDD.llista()
		# Limpia la llista
		self.configuracioLlista.clear()
		# Recorre la llista DATA i omple la llista
		for i in self.DATA:
			self.configuracioLlista.append([i['id'], i['visible'], i['nom'], i['usuari'], "*****", i['dir']])
		


class configuracioBBDD:
	""" Operacions sobre la base de dades """

	def __init__(self):
		
		# Crea la connexió a la BBDD, si no existeix, es crea la taula buida
		import sqlite3
		self.con = sqlite3.connect('config.conf')
		self.taula = self.con.cursor()
		try:
			self.taula.execute('CREATE TABLE IF NOT EXISTS calendaris(id integer primary key, visible text, nom text, direccio text, usuari text, password text)')
		except sqlite3.OperationalError, msg:
			print msg
		
		# S'instancia la classe configuració i es crea una taula amb els valors dels calendaris
		self.taula_calendaris = self.llista()
				
	def __del__(self):
	# Tanca la connexió a la BBDD
		self.taula.close()
		self.con.close()
		
	def insertar(self, visible, nom, usuari, password, direccio):
		self.taula.execute('INSERT INTO calendaris (id, visible, nom, usuari, password, direccio) VALUES (null,"%s","%s","%s","%s","%s")' % (visible, nom, usuari, password, direccio))
		self.con.commit()

	def actualitzar(self, id, visible, nom, usuari, password, direccio):
		self.taula.execute('UPDATE calendaris SET visible="%s", nom="%s", usuari="%s", password="%s", direccio="%s" WHERE id="%s"' % (visible, nom, usuari, password, direccio, id))
		self.con.commit()

	def eliminar(self, id_selec):
		#print ('DELETE FROM calendaris WHERE id="%s"' % id_selec)
		self.taula.execute('DELETE FROM calendaris WHERE id="%s"' % id_selec)
		self.con.commit()
		
	def consulta(self, id, camp):
		self.taula.execute('SELECT "%s" FROM calendaris WHERE id="%s"' % (camp, id))
		self.con.commit()
		for item in self.taula:
			return item[0]

	def llista(self, *args):
	# Retorna en una llista de diccionaris amb la configuracio de cada calendari
		self.taula.execute('SELECT id, visible, nom, usuari, password, direccio FROM calendaris')
		self.con.commit()
		dic_registres = {}
		llista_calendaris = []
				
		for fila in self.taula:
			dic_registres = {'id' : fila[0], 'visible' : fila[1], 'nom' : fila[2], 'usuari' : fila[3], 'password' : fila[4], 'dir' : fila[5]}
			llista_calendaris.append (dic_registres)
		return llista_calendaris
		
		
if __name__ == '__main__':
	EnGoCa(False)
